/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.etrs.formathlon.vue.jsf.form.admin;

import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import net.etrs.formathlon.control.exception.ExceptionManager;
import net.etrs.formathlon.entity.utilisateur.Utilisateur;
import net.etrs.formathlon.metier.service.uc6.rechercheLDAP.LDAPSearchPerson;
import net.etrs.formathlon.metier.utils.constantes.Parametres;
import net.etrs.formathlon.metier.utils.constantes.RoleSpring;
import net.etrs.formathlon.persistance.utilisateur.PersonnelFacade;
import net.etrs.formathlon.persistance.utilisateur.UtilisateurFacade;
import net.etrs.formathlon.vue.jsf.utils.CUDBean;
import org.apache.commons.collections.CollectionUtils;
import org.primefaces.model.DualListModel;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.odm.core.OdmManager;

/**
 * Bean managé JSF pour l'administration des utilisateurs.
 * Utilisateurs regroupe les comptes utilisateurs(technique)
 * ainsi que les personnel(fonctionnel).
 * @author OPIF
 */
@ManagedBean
@ViewScoped
public class AdminUtilisateursBean extends CUDBean<Utilisateur, UtilisateurFacade> {
    //#######################################
    //##            Attributs              ##
    //#######################################

    /**
     * Injection de dépendance de l'odmManager qui
     * fait le lien avec LDAP pour les recherches
     * ponctuelles.
     */
    @ManagedProperty(value = "#{odmManager}")
    private OdmManager odmManager;
    /**
     * Injection de dépendance des deux facades pour la persistence.
     */
    @EJB
    private UtilisateurFacade facade;
    @EJB
    private PersonnelFacade personnefacade;

    /**
     * Liste des personnels utilisés dans la page de listing
     * des personnels.
     */
    private List<Utilisateur> listPersonnels;
    /**
     * Boolean qui spécifie si on doit ajouter un personnel lors de la persistance
     * de l'utilisateur, il conditionne aussi l'affichage des infos complementaire
     * du personnel.
     */
    private boolean ajoutPersonnel;
    /**
     * Boolean qui est défini lors duy setCurrentUtilisateur, il ma spécifier les boutons 
     * à afficher sur la page gestion d'un utilisateur.
     */
    private boolean nouveauUtil;
    /**
     * Attribut nécéssaire au pick list de prime faces.
     */
    private DualListModel<RoleSpring> roles;
    /**
     * champ de recherche vers LDAP 
     */
    private String nomARechercher;

    //#######################################
    //##            Constructeur           ##
    //#######################################
    /**
     * Constructeur par défaut.
     */
    public AdminUtilisateursBean() {
    }

    //#######################################
    //##            Methodes               ##
    //#######################################

     /**
     * Procedure d'initialisation des différentes variables.
     * Elle est appelé en post construct et pour remettre à zero les champs
     * de la page gestion d'un utilisateur.
     */
    @PostConstruct
    @Override
    protected void init() {
        super.init();
        listPersonnels = facade.getPersonnels();
        ajoutPersonnel = false;
        nouveauUtil = true;
        nomARechercher = "";

        List<RoleSpring> roleSource = RoleSpring.getListValue();
        List<RoleSpring> roleTarget = getEntite().getListRoleSpring();
        roles = new DualListModel<RoleSpring>(roleSource, roleTarget);

    }

    /**
     * Methode qui va chercher via un odmManager les informations d'un utilisateurs
     * contenu dans le LDAP.
     */
    //TODO : Deplacer vers une classe util
    public void rechercheLDAP() {
        try {
            if (odmManager == null) {
                throw new Exception("Erreur d'injection de l'odmManager");
            }
            displayMessage("recherche de : " + getNomARechercher());
            List<LDAPSearchPerson> listLDAPSearchPersons = rechercherPersonByUid(getNomARechercher());

            LDAPSearchPerson ldapSearchPerson = listLDAPSearchPersons.get(0);

            getEntite().setMail(ldapSearchPerson.getMail());
            getEntite().setEntite(ldapSearchPerson.getDepartement());
            getEntite().setLogin(ldapSearchPerson.getUid());
            getEntite().getPersonnel().setGrade(ldapSearchPerson.getGrade());
            getEntite().getPersonnel().setNom(ldapSearchPerson.getNom());
            getEntite().getPersonnel().setPrenom(ldapSearchPerson.getPrenom());
        } catch (Exception ex) {
            displayAlert("Aucune correspondance trouvé dans le LDAP.");
        }

    }

    /**
     * Methode d'appel de la recherche LDAP qui va chercher dans le LDAP l'utilisateur
     * ayant uid passé en paramètre.
     * @param a_Uid
     * @return List<LDAPSearchPerson> liste des utilisateurs répondant aux critère de la recherche.
     * @throws Exception 
     */
    public List<LDAPSearchPerson> rechercherPersonByUid(String a_Uid) {
        List<LDAPSearchPerson> people = null;

        // Critère de la recherche
        String critereRecherche = "uid=" + a_Uid;
        if (odmManager != null) {
            people = odmManager.search(LDAPSearchPerson.class,
                    new DistinguishedName(Parametres.CHEMIN_RECHERCHE_LDAP), critereRecherche, Parametres.searchControls);
        }
        return people;
    }

    /**
     * Action appelée par le bouton ajout de la page gestion d'un utilisateur
     * Va mettre en base après controle.
     */
    @Override
    public void creer() {
        try {
            if (!getEntite().getLogin().equals("")) {
                if (!ajoutPersonnel) {
                    getEntite().setPersonnel(null);
                }
                getEntite().setListRoleSpring(roles.getTarget());

                facade.create(getEntite());
                if (ajoutPersonnel) {

                    getEntite().getPersonnel().setUtilisateur(getEntite());

                }
                facade.update(getEntite());

                init();
                displayMessage("Utilisateur ajouté");
            } else {
                displayAlert("Aucun compte LDAP associé");
            }
        } catch (Exception e) {
            // TODO Gérer avec le gestionnaire d'erreur.
            displayAlert("Un utilisateur existe déja avec ce login windows.");
            init();
        }
    }

    /**
     * Action appelée lors de la sauvegarde de la modification d'un utilisateur 
     * sur la page de gestion d'un utilisateur.
     * @return goliste Action jsf qui va appeler la page de listing des utilisateurs.
     */
    public String save() {
        if (!ajoutPersonnel) {

            if (getCurrentUtilisateur().getPersonnel().getUtilisateur() != null) {
                personnefacade.delete(getCurrentUtilisateur().getPersonnel());
            }
            getCurrentUtilisateur().setPersonnel(null);

        } else {
            getCurrentUtilisateur().getPersonnel().setUtilisateur(getCurrentUtilisateur());
        }
        getCurrentUtilisateur().setListRoleSpring(roles.getTarget());

        facade.update(getCurrentUtilisateur());
        init();
        displayMessage("Utilisateur modifié");
        return "goliste";
    }

    /**
     * Méthode appelée lors de la validation de la suppression dans le pop up,
     * pour la suppression d'un utilisateur il faut d'abord supprimer le
     * personnel associé s'il existe.
     */
    @Override
    public void confirmer() {
        try {
            // Test d'existence d'un utilisateur associé et suppression si c'est
            // Le cas
            if (getCurrentUtilisateur().getPersonnel() != null) {
                try {
                    personnefacade.delete(getCurrentUtilisateur().getPersonnel());
                } catch (Exception e) {
                    // Rien a faire c'est qu'il n'existe pas mais ça evite un test de
                    // faire comme ça
                }
            }
            // Suppression de l'utilisateur
            facade.delete(getCurrentUtilisateur());
            // Mise à jours des listes pour eviter de refaire un init et un recherche
            // en base
            init();
            displayMessage("Suppression de l'utilisateur réussie.");
        } catch (Exception ex) {
            displayErreur(ExceptionManager.traiter(ex));
        }
    }

    /**
     * Methode appelée lors du retour negatif de la confirmation de suppression.
     */
    @Override
    public void infirmer() {
    }

    /**
     * Action appelée dans comptes_utilisateurs_liste et personnels_liste qui
     * va charger dans le currentUtilisateur l'utilisateur du tableau choisi
     * puis appeler le pop up de confirmation qui appelera les methodes confirmer()
     * ou infirmer() selon le choix fait à la confirmation.
     * @param user 
     */
    public void supprimer(Object user) {

        super.supprimer((Utilisateur) user);

    }

    /**
     * Annule la saisie de création ou de modification de l'utilisateur.
     * @return Le cas de navigation pour revenir sur la liste
     */
    public String retourListe() {
        return "goliste";
    }

    /**
     * Equivaut à la remise à zéro.
     */
    public void raz() {
        init();
    }

    //#######################################
    //##        GETTER ET SETTER           ##
    //#######################################
    /**
     * Setter du currentUtilisateur qu'on va utiliser pour l'initialisation 
     * des diçfférentes variables d'affichage.
     * @param currentUtilisateur 
     */
    public void setCurrentUtilisateur(Utilisateur currentUtilisateur) {
        setEntite(currentUtilisateur);

        // Construction du DualListModel necessaire au pick list JSF
        List<RoleSpring> roleSource = RoleSpring.getListValue();
        List<RoleSpring> roleTarget = this.getCurrentUtilisateur().getListRoleSpring();
        roles = new DualListModel<RoleSpring>((List<RoleSpring>) CollectionUtils.subtract(roleSource, roleTarget), roleTarget);

        // Test si le champ login est vide
        // si oui on est dans le cas de l'ajout d'un nouvelle
        // utilisateur et on initialise une variable qui servira
        // a l'affichage des bon boutons dans la vue
        if (currentUtilisateur.getLogin().equals("")) {
            nouveauUtil = true;
        } else {
            nouveauUtil = false;
        }

        // Test si l'utilisateur possède un personne correspondant qui n'est pas
        // dans l'état par défaut de son iniialisation afin d'initialiser la variable
        // qui servira a cacher ou afficher le panel des informations complementaire

        if (currentUtilisateur.getPersonnel().getUtilisateur() != null) {

            ajoutPersonnel = true;
        }
    }

    /**
     * 
     * @return nomARechercher
     */
    public String getNomARechercher() {
        return nomARechercher;
    }

    /**
     * 
     * @param nomARechercher 
     */
    public void setNomARechercher(String nomARechercher) {
        this.nomARechercher = nomARechercher;
    }

    /**
     * 
     * @return nouveauUtil
     */
    public boolean isNouveauUtil() {
        return nouveauUtil;
    }

    /**
     * 
     * @param nouveauUtil 
     */
    public void setNouveauUtil(boolean nouveauUtil) {
        this.nouveauUtil = nouveauUtil;
    }

    /**
     * 
     * @return odmManager
     */
    public OdmManager getOdmManager() {
        return odmManager;
    }

    /**
     * 
     * @param odmManager 
     */
    public void setOdmManager(OdmManager odmManager) {
        this.odmManager = odmManager;
    }

    /**
     * 
     * @return ajoutPersonnel
     */
    public boolean isAjoutPersonnel() {
        return ajoutPersonnel;
    }

    /**
     * 
     * @param ajoutPersonnel 
     */
    public void setAjoutPersonnel(boolean ajoutPersonnel) {
        this.ajoutPersonnel = ajoutPersonnel;
    }

    /**
     * 
     * @return roles
     */
    public DualListModel<RoleSpring> getRoles() {
        return roles;
    }

    /**
     * 
     * @param roles 
     */
    public void setRoles(DualListModel<RoleSpring> roles) {
        this.roles = roles;
    }

    /**
     * 
     * @return currentUtilisateur
     */
    public Utilisateur getCurrentUtilisateur() {
        return getEntite();
    }

    /**
     * 
     * @return listPersonnels
     */
    public List<Utilisateur> getListPersonnels() {
        return listPersonnels;
    }

    /**
     * 
     * @param listPersonnels 
     */
    public void setListPersonnels(List<Utilisateur> listPersonnels) {
        this.listPersonnels = listPersonnels;
    }

    /**
     * 
     * @return listUtilisateurs
     */
    public List<Utilisateur> getListUtilisateurs() {
        return getListEntite();
    }

    /**
     * 
     * @return personnefacade
     */
    public PersonnelFacade getPersonnefacade() {
        return personnefacade;
    }

    /**
     * 
     * @param personnefacade 
     */
    public void setPersonnefacade(PersonnelFacade personnefacade) {
        this.personnefacade = personnefacade;
    }

    /**
     * 
     * @return utilisateurFacade
     */
    public UtilisateurFacade getUtilisateurFacade() {
        return facade;
    }

    /**
     * 
     * @param utilisateurFacade 
     */
    public void setUtilisateurFacade(UtilisateurFacade utilisateurFacade) {
        this.facade = utilisateurFacade;
    }

    @Override
    protected UtilisateurFacade getFacade() {
        return facade;
    }
}
